package org.hdlh;

import io.netty.channel.DefaultEventLoop;
import io.netty.util.concurrent.DefaultPromise;
import lombok.extern.slf4j.Slf4j;
import org.hdlh.constants.ReqType;
import org.hdlh.constants.RpcConstants;
import org.hdlh.constants.SerialType;
import org.hdlh.core.*;
import org.hdlh.protocol.NettyClient;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 实现
 */
@Slf4j
public class RpcInvokerProxy implements InvocationHandler {

    private String host;
    private int port;

    public RpcInvokerProxy(String host, int port) {
        this.host = host;
        this.port = port;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log.info("being invoke target server");
        RpcProtocol<RpcRequest> rpcRequestRpcProtocol = new RpcProtocol<>();
        long requestId = RequestHolder.REQUEST_ID.incrementAndGet();
        Header header = new Header(RpcConstants.MAGIC, SerialType.JSON_SERIAL.code(),
                ReqType.REQUEST.code(), requestId, 0);


        rpcRequestRpcProtocol.setHeader(header);
        RpcRequest request = new RpcRequest();
        request.setClassName(method.getDeclaringClass().getName());
        request.setMethodName(method.getName());
        request.setParams(args);
        request.setParameterTypes(method.getParameterTypes());

        rpcRequestRpcProtocol.setContent(request);
        NettyClient nettyClient = new NettyClient(host, port);

        RpcFuture<RpcResponse> future = new RpcFuture<>(new DefaultPromise<RpcResponse>( new DefaultEventLoop()));
        RequestHolder.REQUEST_MAP.put(requestId, future);
        nettyClient.sendRequest(rpcRequestRpcProtocol);

        return future.getPromise().get().getData();
    }
}
